from manim import *

class VectorRelations(Scene):
    def construct(self):
        # 定义向量
        a = np.array([1, 0])
        two_a = 2 * a
        b = np.array([1/4, np.sqrt(7)/4])
        b_minus_2a = b - two_a
        b_radius = 1  # 圆的半径

        # 绘制坐标系
        plane = NumberPlane(
            x_range=[-3, 3, 1],
            y_range=[-3, 3, 1],
            background_line_style={
                "stroke_color": BLUE_D,
                "stroke_width": 1,
                "stroke_opacity": 0.6
            }
        )
        self.add(plane)

        # 绘制向量
        vector_a = Arrow(start=plane.c2p(0, 0), end=plane.c2p(*a), buff=0, color=BLUE)
        vector_2a = Arrow(start=plane.c2p(0, 0), end=plane.c2p(*two_a), buff=0, color=ORANGE)
        vector_b = Arrow(start=plane.c2p(0, 0), end=plane.c2p(*b), buff=0, color=GREEN)
        vector_b_minus_2a = Arrow(start=plane.c2p(*two_a), end=plane.c2p(*b), buff=0, color=RED)

        # 添加向量标签
        label_a = MathTex(r"\mathbf{a}").next_to(vector_a.get_end(), UP)
        label_2a = MathTex(r"2\mathbf{a}").next_to(vector_2a.get_end(), UP)
        label_b = MathTex(r"\mathbf{b}").next_to(vector_b.get_end(), UP)
        label_b_minus_2a = MathTex(r"\mathbf{b} - 2\mathbf{a}").next_to(vector_b_minus_2a.get_end(), UP)

        # 显示向量和标签，并移除标签
        self.play(Create(vector_a), Write(label_a))
        self.wait(1)
        self.play(FadeOut(label_a))

        self.play(Create(vector_2a), Write(label_2a))
        self.wait(1)
        self.play(FadeOut(label_2a))

        self.play(Create(vector_b), Write(label_b))
        self.wait(1)
        self.play(FadeOut(label_b))

        self.play(Create(vector_b_minus_2a), Write(label_b_minus_2a))
        self.wait(1)
        self.play(FadeOut(label_b_minus_2a))

        # 保持图像
        self.wait(2)

        # 添加文字说明
        explanation = Text(
            "由于向量 \\(\\mathbf{b}\\) 与向量 \\(\\mathbf{b} - 2\\mathbf{a}\\) 垂直，\n"
            "因此可以得出向量 \\(\\mathbf{b}\\) 在以 (1, 0) 为圆心的圆上运动。",
            font_size=24
        ).to_edge(UP)
        self.play(Write(explanation))

        # 绘制圆
        circle_center = plane.c2p(1, 0)  # 圆心为 (1, 0)
        circle = Circle(radius=b_radius, color=YELLOW).move_to(circle_center)
        self.play(Create(circle))

        # 修改原来的向量b的重点，例如，取到（1，1）点，然后重新绘制b和b_minus_2a向量
        # 更新向量b的终点到新位置，例如到（1，1）点
        new_b = np.array([1, 1])
        new_vector_b = Arrow(start=plane.c2p(0, 0), end=plane.c2p(*new_b), buff=0, color=GREEN)
        new_vector_b_minus_2a = Arrow(start=plane.c2p(*two_a), end=plane.c2p(*new_b), buff=0, color=RED)
        # 使用Transform动画更新向量
        self.play(Transform(vector_b, new_vector_b), Transform(vector_b_minus_2a, new_vector_b_minus_2a))
        # 保持图像
        self.wait(1)

        # 以原点为圆心，2为半径，画一个红色的圆形
        circle_2 = Circle(radius=2, color=RED).move_to(plane.c2p(0, 0))
        self.play(Create(circle_2))

        # 现在添加向量a+2b的演示
        # 计算向量a+2b
        vector_a_plus_2b = a + 2 * b
        # 创建表示向量a+2b的箭头
        arrow_a_plus_2b = Arrow(start=plane.c2p(0, 0), end=plane.c2p(*vector_a_plus_2b), buff=0, color=PURPLE)
        # 添加向量a+2b的标签
        label_a_plus_2b = MathTex(r"\mathbf{a} + 2\mathbf{b}").next_to(arrow_a_plus_2b.get_end(), UP)

        # 展示向量a+2b及其标签
        self.play(Create(arrow_a_plus_2b), Write(label_a_plus_2b))
        self.wait(1)

        # 如何展示调整向量b，使得向量vector_a_plus_2b刚好模为2，也即是落在circle_2上？
        # 计算向量a的终点
        end_a = a

        # 假设我们想要向量a+2b的终点落在圆上的点P(x, y)，这里我们随便取一个点
        # 例如，我们取45度角的点，这只是为了示例，你可以根据需要选择不同的点
        angle = PI / 4
        end_p = np.array([2 * np.cos(angle), 2 * np.sin(angle)])  # 圆的半径是2

        # 计算新的向量b的终点
        new_end_b = (end_p - end_a) / 2

        # 创建新的向量b
        new_vector_b = Arrow(start=plane.c2p(0, 0), end=plane.c2p(*new_end_b), buff=0, color=GREEN)
        label_new_b = MathTex(r"new \ \mathbf{b}").next_to(new_vector_b.get_end(), UP)

        # 创建新的向量a+2b
        new_arrow_a_plus_2b = Arrow(start=plane.c2p(0, 0), end=plane.c2p(*end_p), buff=0, color=PURPLE)
        label_new_a_plus_2b = MathTex(r"\mathbf{a} + 2 \cdot new \ \mathbf{b}").next_to(new_arrow_a_plus_2b.get_end(), UP)
        new_vector_b_minus_2a = Arrow(start=plane.c2p(*two_a), end=plane.c2p(*new_end_b), buff=0, color=RED)
        # 使用动画展示新的向量b和a+2b
        self.play(Transform(vector_b, new_vector_b), Transform(arrow_a_plus_2b, new_arrow_a_plus_2b))
        self.play(Transform(label_b, label_new_b), Transform(label_a_plus_2b, label_new_a_plus_2b))

        # 更新并展示新的向量b_minus_2a
        new_vector_b_minus_2a = Arrow(start=plane.c2p(*two_a), end=plane.c2p(*new_end_b), buff=0, color=RED)
        label_new_b_minus_2a = MathTex(r"new \ \mathbf{b} - 2\mathbf{a}").next_to(new_vector_b_minus_2a.get_end(), UP)

        self.play(Transform(vector_b_minus_2a, new_vector_b_minus_2a), Write(label_new_b_minus_2a))

        # 保持图像
        self.wait(2)


